package com.ljy.my_study.leetcode.恢复二叉搜索树;

import com.ljy.my_study.util.TreeNodeUtil;
import com.ljy.my_study.util.TreeNodeUtil.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lijunying
 * @date 2021/11/16 14:08
 */
public class TestMain {

//    给你二叉搜索树的根节点 root ，该树中的两个节点被错误地交换。请在不改变其结构的情况下，恢复这棵树。
//
//    进阶：使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗？
//
//             
//
//    示例 1：
//
//
//    输入：root = [1,3,null,null,2]
//    输出：[3,1,null,null,2]
//    解释：3 不能是 1 左孩子，因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
//    示例 2：
//
//
//    输入：root = [3,1,4,null,null,2]
//    输出：[2,1,4,null,null,3]
//    解释：2 不能在 3 的右子树中，因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
//             
//
//    提示：
//
//    树上节点的数目在范围 [2, 1000] 内
//-2^31 <= Node.val <= 2^31 - 1
//
//    来源：力扣（LeetCode）
//    链接：https://leetcode-cn.com/problems/recover-binary-search-tree
//    著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。

    public static void main(String[] args) {
//        TreeNode root=TreeNodeUtil.deserialize("1,3,null,null,2");
//        new TestMain().recoverTree(root);
//        System.out.println(root);
//        TreeNode root=TreeNodeUtil.deserialize("3,1,4,null,null,2");
        TreeNode root=TreeNodeUtil.deserialize("3,null,2,null,null,null,1");
//        TreeNode root=TreeNodeUtil.deserialize("2,3,1");
        new TestMain().recoverTree(root);
        System.out.println(root);
    }
//    显式中序遍历
//    将数据都拿出来排序对比提取两个错误位置的值
    public void recoverTree(TreeNode root) {
        List<TreeNode> nums = new ArrayList<>();
        inorder(root, nums);
        TreeNode[] swapped = findTwoSwapped(nums);
        swap(swapped[0],swapped[1]);
    }

    public void inorder(TreeNode root, List<TreeNode> nums) {
        if (root == null) {
            return;
        }
        inorder(root.left, nums);
        nums.add(root);
        inorder(root.right, nums);
    }

    public TreeNode[] findTwoSwapped(List<TreeNode> nums) {
        int n = nums.size();
        int index1 = -1, index2 = -1;
        for (int i = 0; i < n - 1; ++i) {
            if (nums.get(i + 1).val < nums.get(i).val) {
                index2 = i + 1;
                if (index1 == -1) {
                    index1 = i;
                } else {
                    break;
                }
            }
        }
        TreeNode x = nums.get(index1), y = nums.get(index2);
        return new TreeNode[]{x, y};
    }

    private void swap(TreeNode a,TreeNode b){
        int tmp=a.val;
        a.val=b.val;
        b.val=tmp;
    }
}
